/*
    Churned Ajax Toolkit
    http://www.codeplex.com/ChurnedAjaxToolkit

    This source is subject to the Microsoft Permissive License.
    All other rights reserved.

    Version:  1.0.1 released 25 April 2008
*/

Type.registerNamespace('ChurnedAjaxToolkit');

ChurnedAjaxToolkit.TextEditActivationMode = function() { 
    throw Error.invalidOperation(); 
}
ChurnedAjaxToolkit.TextEditActivationMode.prototype = {
    Hover : 0,
    SingleClick : 1,
    DoubleClick : 2
}
ChurnedAjaxToolkit.TextEditActivationMode.registerEnum("ChurnedAjaxToolkit.TextEditActivationMode", false);

ChurnedAjaxToolkit.TextEditHoverActivationDelay = function() { throw Error.invalidOperation(); }
ChurnedAjaxToolkit.TextEditHoverActivationDelay.prototype = {
    Immediate : 0,
    Fast : 200,
    Medium : 400,
    Slow : 600
}
ChurnedAjaxToolkit.TextEditHoverActivationDelay.registerEnum("ChurnedAjaxToolkit.TextEditHoverActivationDelay", false);

ChurnedAjaxToolkit.TextEditArgs = function(editText, displayText) {
    ChurnedAjaxToolkit.TextEditArgs.initializeBase(this);
    
    this._editText = editText;
    this._displayText = displayText;
    this._handled = false;
}
ChurnedAjaxToolkit.TextEditArgs.prototype = {
    get_editText : function() { return this._editText; },
    set_editText : function(value) { this._editText = value; },
    
    get_displayText : function() { return this._displayText; },
    set_displayText : function(value) { this._displayText = value; },
    
    get_handled : function() { return this._handled; },
    set_handled : function(value) { this._handled = value; }
}
ChurnedAjaxToolkit.TextEditArgs.registerClass('ChurnedAjaxToolkit.TextEditArgs', Sys.EventArgs);

ChurnedAjaxToolkit.TextEditBehavior = function(element) {
    ChurnedAjaxToolkit.TextEditBehavior.initializeBase(this, [element]);

    // Properties and Default Values
    this._activationMode = ChurnedAjaxToolkit.TextEditActivationMode.SingleClick;
    this._blankText = '';
    this._hoverActivationDelay = ChurnedAjaxToolkit.TextEditHoverActivationDelay.Fast;
    this._labelCssClass = '';
    this._labelHoverCssClass = '';
    this._labelTooltipText = '';
    this._maxTextboxHeight = null;
    this._maxTextboxWidth = null;
    this._minTextboxHeight = 0;
    this._minTextboxWidth = 0;
    this._ResizeTextboxHeight = true;
    this._ResizeTextboxWidth = true;
    this._textboxCssClass = '';
    this._textboxTooltipText = '';
       
    // Label Handlers
    this._labelClickHandler = null;
    this._labelMouseOverHandler = null;
    this._labelMouseOutHandler = null;
    this._labelDoubleClickHandler = null;
    
    // Textbox Handlers
    this._textboxBlurHandler = null;
    this._textboxFocusHandler = null;
    
    // The label for display mode
    this._label = null;
    
    // Used when ActivationMode = Hover to implement HoverActivationDelay
    this._hoverTimer = null;
    
    // Tells us if we are currently in edit mode
    this._isEditing = true;
    
    // Stores the original size of the textbox.
    this._originalBounds = null;
}
ChurnedAjaxToolkit.TextEditBehavior.prototype = {
    initialize : function() {
        ChurnedAjaxToolkit.TextEditBehavior.callBaseMethod(this, 'initialize');

        // Get the control we are extending
        var textbox = this.get_element();
        
        // Save the original size of the textbox
        this._originalBounds = Sys.UI.DomElement.getBounds(textbox);
        
        // Create the label element
        this._label = document.createElement("span");
        this._label.id = "lbl_" + textbox.id;
        textbox.parentNode.insertBefore(this._label,textbox);
        
        // Set the css classes
        if (this._textboxCssClass) { Sys.UI.DomElement.addCssClass(textbox,this._textboxCssClass); }
        if (this._labelCssClass) { Sys.UI.DomElement.addCssClass(this._label,this._labelCssClass); }
        Sys.UI.DomElement.addCssClass(textbox,"transparent_class");
        
        // Set the tooltips
        this._label.title = this._labelTooltipText;
        textbox.title = this._textboxTooltipText;
        
        // Add the handlers
        this._attachHandlers();

        // Display the label initially
        this.exitEditMode();
    },

    dispose : function() {
        // Get the control we are extending
        var textbox = this.get_element();
        
        // Remove the handlers
        this._detachHandlers();

        ChurnedAjaxToolkit.TextEditBehavior.callBaseMethod(this, 'dispose');
    },
 
    _attachHandlers: function() {
        var textbox = this.get_element();
        
        // Label Handlers
        switch(this._activationMode) {
            case ChurnedAjaxToolkit.TextEditActivationMode.Hover:
                this._labelMouseOverHandler = Function.createDelegate(this,this.startHoverDelay);
                this._labelMouseOutHandler = Function.createDelegate(this,this.stopHoverDelay);
                $addHandlers(this._label,{mouseover:this._labelMouseOverHandler,mouseout:this._labelMouseOutHandler});
                break;
            case ChurnedAjaxToolkit.TextEditActivationMode.SingleClick:
                this._labelClickHandler = Function.createDelegate(this,this._labelOnClick);
                this._labelMouseOverHandler = Function.createDelegate(this,this._labelOnMouseOver);
                this._labelMouseOutHandler = Function.createDelegate(this,this._labelOnMouseOut);
                $addHandlers(this._label,{click:this._labelClickHandler,mouseover:this._labelMouseOverHandler,mouseout:this._labelMouseOutHandler});
                break;
            case ChurnedAjaxToolkit.TextEditActivationMode.DoubleClick:
                this._labelDoubleClickHandler = Function.createDelegate(this,this._labelOnDoubleClick);
                this._labelMouseOverHandler = Function.createDelegate(this,this._labelOnMouseOver);
                this._labelMouseOutHandler = Function.createDelegate(this,this._labelOnMouseOut);
                $addHandlers(this._label,{dblclick:this._labelDoubleClickHandler,mouseover:this._labelMouseOverHandler,mouseout:this._labelMouseOutHandler});
                break; 
        }
        // Textbox Handlers
        this._textboxBlurHandler = Function.createDelegate(this,this._textboxOnBlur);
        $addHandler(textbox,"blur",this._textboxBlurHandler);  
        
        this._textboxFocusHandler = Function.createDelegate(this,this._textboxOnFocus);
        $addHandler(textbox,"focus",this._textboxFocusHandler);  
   },
    
    _detachHandlers : function() {
        var textbox = this.get_element();
        
        // Label Handlers
        if (this._labelClickHandler)  {
            $removeHandler(this._label,"click",this._labelClickHandler);
            this._labelClickHandler = null;
        }
        if (this._labelDoubleClickHandler) {
            $removeHandler(this._label,"dblclick",this._labelDoubleClickHandler);
            this._labelDoubleClickHandler = null;
        }
        if (this._labelMouseOverHandler) {
            $removeHandler(this._label,"mouseover",this._labelMouseOverHandler);
            this._labelMouseOverHandler = null;
        }
        if (this._labelMouseOutHandler) {
            $removeHandler(this._label,"mouseout",this._labelMouseOutHandler);
            this._labelMouseOutHandler = null;
        } 
         
        // Textbox Handlers
        if (this._textboxBlurHandler) {
            $removeHandler(textbox,"blur",this._textboxBlurHandler);
            this._textboxBlurHandler = null;
        }
        
        if (this._textboxFocusHandler) {
            $removeHandler(textbox,"focus",this._textboxFocusHandler);
            this._textboxFocusHandler = null;
        }
    },
    
    _labelOnClick : function(e) {
        this.enterEditMode();
    },
    
    _labelOnDoubleClick : function(e) {
        this.enterEditMode();
    },
        
    _textboxOnFocus : function(e) {
        this.enterEditMode();
    },
    
    _labelOnMouseOver : function(e) {
        if (this._labelHoverCssClass) {
            Sys.UI.DomElement.addCssClass($get(this._label.id),this._labelHoverCssClass);
        }
    },
    
    _labelOnMouseOut : function(e) {
        if (this._labelHoverCssClass) {
            Sys.UI.DomElement.removeCssClass($get(this._label.id),this._labelHoverCssClass);
        }
    },
    
    startHoverDelay: function(e) {
        this._hoverTimer = window.setTimeout(Function.createDelegate(this, this.enterEditMode), this._hoverActivationDelay);
        this._labelOnMouseOver();
    },
    
    stopHoverDelay: function(e) {
        clearTimeout(this._hoverTimer);
        this._labelOnMouseOut();
    },
    
    _textboxOnBlur: function(e) {
        this.exitEditMode();
    },
    
    enterEditMode: function() {
        if (this.get_element() && !this.get_element().disabled && !this._isEditing) {
            var textbox = this.get_element();
            
            // Adjust the size of the textbox
            var width,height;
            labelBounds = Sys.UI.DomElement.getBounds($get(this._label.id)); 
            if (this._ResizeTextboxWidth) { 
                if (this._minTextboxWidth > 0 && labelBounds.width < this._minTextboxWidth) width = this._minTextboxWidth;
                else if (this._maxTextboxWidth != null && labelBounds.width > this._maxTextboxWidth) width = this._maxTextboxWidth;
                else { width = labelBounds.width; }
            } else {
                width = this._originalBounds.width;
            }
           
            if (this._ResizeTextboxHeight) {
                if (this._minTextboxHeight > 0 && labelBounds.height < this._minTextboxHeight) height = this._minTextboxHeight;
                else if (this._maxTextboxHeight != null && labelBounds.height > this._maxTextboxHeight) height = this._maxTextboxHeight;
                else { height = labelBounds.height; }
            } else { 
                height = this._originalBounds.height;
            }
           
            textbox.style.width = (width + 10) + 'px';
            textbox.style.height = height + 'px';

            // Hide the label and show the textbox            
            Sys.UI.DomElement.removeCssClass(this.get_element(),"transparent_class");
            this._label.style.display='none';
            
            // Now in edit mode
            this._isEditing = true;
        
            // Select the input for editing.   This must be done after isEditing is set
            textbox.select();
        }
    },
    
    exitEditMode: function() {
        if (this.get_element() && !this.get_element().disabled && this._isEditing) {
            var textbox = this.get_element();
            
            // Client callback so the display text can be modified.
            // Example:  html encode the user input
            var eventArgs = new ChurnedAjaxToolkit.TextEditArgs(textbox.value,null);
            this.raiseClientEdited(eventArgs);
            this._label.innerHTML = eventArgs.get_handled()?eventArgs.get_displayText():eventArgs.get_editText();
            
            // Plug in the BlankText if the user input is empty
            if (!this._label.innerHTML) { this._label.innerHTML = this._blankText; }
            
            // Hide the textbox and show the label
            Sys.UI.DomElement.addCssClass(this.get_element(),"transparent_class");
            this._label.style.display='';
            
            // No longer in edit mode
            this._isEditing = false;
        }
    },
    
    get_ActivationMode: function() { return this._activationMode; },
    set_ActivationMode: function(value) { this._activationMode = value; },
    
    get_BlankText : function() { return this._blankText; },
    set_BlankText : function(value) {this._blankText = value; },
    
    add_clientEdited : function(handler) { this.get_events().addHandler("clientEdited",handler); },
    remove_clientEdited : function(handler) { this.get_events().removeHandler('clientEdited',handler); },
    raiseClientEdited : function(eventArgs) {
        var handler = this.get_events().getHandler('clientEdited');
        if (handler) { handler(this,eventArgs); }
    },

    get_HoverActivationDelay: function() { return this._hoverActivationDelay; },
    set_HoverActivationDelay: function(value) { this._hoverActivationDelay = value; },
    
    get_LabelCssClass : function() { return this._labelCssClass; },
    set_LabelCssClass : function(value) { this._labelCssClass = value; },
    
    get_LabelHoverCssClass : function() { return this._labelHoverCssClass; },
    set_LabelHoverCssClass : function(value) { this._labelHoverCssClass = value; },
    
    get_LabelTooltipText: function() { return this._labelTooltipText; },
    set_LabelTooltipText: function(value) { this._labelTooltipText = value; },
   
    get_MaxTextboxHeight: function() { return this._maxTextboxHeight; },
    set_MaxTextboxHeight: function(value) { this._maxTextboxHeight = value; },
     
    get_MaxTextboxWidth: function() { return this._maxTextboxWidth; },
    set_MaxTextboxWidth: function(value) { this._maxTextboxWidth = value; },
    
    get_MinTextboxHeight: function() { return this._minTextboxHeight; },
    set_MinTextboxHeight: function(value) { this._minTextboxHeight = value; },
    
    get_MinTextboxWidth: function() { return this._minTextboxWidth; },
    set_MinTextboxWidth: function(value) { this._minTextboxWidth = value; },
    
    get_ResizeTextboxHeight: function() { return this._ResizeTextboxHeight; },
    set_ResizeTextboxHeight: function(value) { this._ResizeTextboxHeight = value; },
    
    get_ResizeTextboxWidth: function() { return this._ResizeTextboxWidth; },
    set_ResizeTextboxWidth: function(value) { this._ResizeTextboxWidth = value; },
    
    get_TextboxCssClass: function() { return this._textboxCssClass; },
    set_TextboxCssClass: function(value) { this._textboxCssClass = value; },
    
    get_TextboxTooltipText: function() { return this._textboxTooltipText; },
    set_TextboxTooltipText: function(value) { this._textboxTooltipText = value; }
    
}
ChurnedAjaxToolkit.TextEditBehavior.registerClass('ChurnedAjaxToolkit.TextEditBehavior', AjaxControlToolkit.BehaviorBase);
